package org.yx.service.smfr.save_scan_material_to_psn_and_print;

import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.util.NumberUtil;
import org.dbist.dml.Query;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.yx.exception.BizException;
import org.yx.models.*;
import org.yx.service.bas.create_rule_code.BasCreateRuleCodeService;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryIn;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryService;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryIn;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryService;
import org.yx.service.smfr.view_product_sn_to_print_label.SmfrViewProductSnToPrintLabelIn;
import org.yx.service.smfr.view_product_sn_to_print_label.SmfrViewProductSnToPrintLabelService;
import org.yx.service.smfr.view_work_order_need_input_material.SmfrViewWorkOrderNeedInputMaterialIn;
import org.yx.service.smfr.view_work_order_need_input_material.SmfrViewWorkOrderNeedInputMaterialService;
import org.yx.utils.BaseService;
import org.yx.utils.FieldMap;
import org.yx.utils.ServiceBeanUtil;

import java.math.BigDecimal;
import java.util.*;

/**
 * 保存原物料扫码投料，生成产品批次，并打印（可选）
 *
 * @author zxw
 * @since 2023/03/23
 **/
public class SmfrSaveScanMaterialToPsnAndPrintService extends BaseService {
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public SmfrSaveScanMaterialToPsnAndPrintOut saveScanMaterialToPsnAndPrint(SmfrSaveScanMaterialToPsnAndPrintIn in) throws Exception {
        checkNumberNotZero(in, "totalQty,outputQty");
        if (CollUtil.isEmpty(in.getMsnStsList())) {
            throw new BizException("SYS-0004", FieldMap.of("parameter", "msnStsList"));
        }

        SmfrOrdDef ordDef = selectWithPk(SmfrOrdDef.class, in.getUserOrgCode(), in.getMsnStsList().get(0).getMo());
        if (ordDef == null || "D".equals(ordDef.getMoStatus())) {
            throw new BizException("SMFR-0004", "生产工单${mo}不存在或已被删除。", FieldMap.of("mo", in.getMsnStsList().get(0).getMo()));
        }

        //BOM待扫清单
        SmfrViewWorkOrderNeedInputMaterialIn needMatIn = new SmfrViewWorkOrderNeedInputMaterialIn();
        needMatIn.setMo(ordDef.getMo());
        List<SbasMatDef> needMatList = ServiceBeanUtil.getBean(SmfrViewWorkOrderNeedInputMaterialService.class).viewWorkOrderNeedInputMaterial(needMatIn).getMatList();
        for (SmatMsnSts inMsn : in.getMsnStsList()) {
            for (int i = 0; i < needMatList.size(); i++) {
                if (inMsn.getMatCode().equals(needMatList.get(i).getMatCode())) {
                    needMatList.remove(i);
                    break;
                }
            }
        }

        if (!CollUtil.isEmpty(needMatList)) {
            for (SbasMatDef mat : needMatList) {
                if ("Y".equals(mat.getTraceFlag())) {
                    //还有需要追溯但未上料的物料
                    throw new BizException("SMFR-0020", "工单${mo}的物料需求中有追溯要求物料${matCode}。",
                            FieldMap.of("mo", ordDef.getMo()), FieldMap.of("matCode", mat.getMatCode()));
                }
            }
        }

        //工艺路线工序
        Query query = new Query();
        query.addFilter("orgCode", ordDef.getOrgCode());
        query.addFilter("pathCode", ordDef.getPathCode());
        query.addFilter("status", "N");
        query.addOrder("seqNum", true);
        List<SmfrPthOpr> pthOprs = selectList(SmfrPthOpr.class, query);
        if (CollUtil.isEmpty(pthOprs)) {
            throw new BizException("SMFR-0005", "工艺路线${pathCode}的工序不存在。", FieldMap.of("pathCode", ordDef.getPathCode()));
        }

        BigDecimal totalQty = in.getTotalQty();
        List<SmfrPsnSts> psnStsList = new ArrayList<SmfrPsnSts>();

        String psnLot = BasCreateRuleCodeService.createRuleCode("PSN_LOT");

        Set<String> psns = new HashSet<String>();
        while (totalQty.compareTo(BigDecimal.ZERO) > 0) {
            //产品批次数量，可以满足尾数
            BigDecimal psnQty = totalQty.compareTo(in.getOutputQty()) > 0 ? in.getOutputQty() : totalQty;
            totalQty = totalQty.subtract(psnQty);

            SmfrPsnSts psnSts = new SmfrPsnSts();
            psnSts.setOrgCode(in.getUserOrgCode());
            psnSts.setPsn(BasCreateRuleCodeService.createRuleCode("PSN"));
            psnSts.setLot(psnLot);
            psnSts.setPsnType("P");
            psnSts.setStatus("N");
            psnSts.setMo(ordDef.getMo());
            psnSts.setMatCode(ordDef.getMatCode());
            psnSts.setMatVer(ordDef.getMatVer());
            psnSts.setPathCode(ordDef.getPathCode());
            psnSts.setOper(pthOprs.get(0).getOper());
            psnSts.setOperSeq(pthOprs.get(0).getSeqNum());
            psnSts.setResId(in.getMsnStsList().get(0).getCarryId());
            psnSts.setDtlSeq(1);
            psnSts.setEventCode("CREATE");
            psnSts.setEventValue("INPUT_MSN");
            psnSts.setQty(psnQty);
            psnSts.setUnit(ordDef.getUnit());
            psnSts.setCurrentLoc(ordDef.getLineCode());

            psnStsList.add(psnSts);

            psns.add(psnSts.getPsn());
        }

        //物料批次信息，生成投料信息
        List<SmatMsnSts> upMsnStsList = new ArrayList<SmatMsnSts>();
        List<SmfrPodMat> podMatList = new ArrayList<SmfrPodMat>();
        for (SmatMsnSts inMsn : in.getMsnStsList()) {
            SmatMsnSts msnSts = selectWithPk(SmatMsnSts.class, in.getUserOrgCode(), inMsn.getMsn());
            msnSts.setQty(msnSts.getQty().subtract(inMsn.getQty()));
            if (msnSts.getQty().compareTo(BigDecimal.ZERO) < 0) {
                throw new BizException("SMFR-0019","用量不正确，物料批次${msn}当前数量${qty}。",
                        FieldMap.of("msn",msnSts.getMsn()),FieldMap.of("qty",msnSts.getQty()));
            }
            msnSts.setDtlSeq(msnSts.getDtlSeq() + 1);
            msnSts.setEventCode("PROD");
            msnSts.setEventValue("INPUT_MSN");
            msnSts.setMo(inMsn.getMo());

            upMsnStsList.add(msnSts);

            SmfrPodMat podMat = new SmfrPodMat();
            podMat.setOrgCode(msnSts.getOrgCode());
            podMat.setPsnLot(psnLot);
            podMat.setMsn(msnSts.getMsn());
            podMat.setMatCode(msnSts.getMatCode());
            podMat.setMatVer(msnSts.getMatVer());
            podMat.setQty(inMsn.getQty());
            podMat.setMo(inMsn.getMo());
            podMat.setResId(inMsn.getCarryId());
            podMat.setStatus("N");
            podMat.setOperUser(in.getUserToken().getUserId());

            podMatList.add(podMat);
        }

        ServiceBeanUtil.getBean(SmfrSaveScanMaterialToPsnAndPrintService.class).saveData(upMsnStsList, psnStsList, podMatList);

        SmfrSaveScanMaterialToPsnAndPrintOut out = new SmfrSaveScanMaterialToPsnAndPrintOut();
        out.setPsnList(psnStsList);

        //创建pdf
        if ("Y".equals(in.getPrintFlag())) {
            String strPsns = CollUtil.join(psns, ",");
            SmfrViewProductSnToPrintLabelIn labelIn = new SmfrViewProductSnToPrintLabelIn();
            labelIn.setPsns(strPsns);
            out.setLabelFileName(ServiceBeanUtil.getBean(SmfrViewProductSnToPrintLabelService.class).viewProductSnToPrintLabel(labelIn).getFileName());
        }

        return out;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void saveData(List<SmatMsnSts> msnList, List<SmfrPsnSts> psnList, List<SmfrPodMat> podMatList) throws Exception {
        insertBatch(podMatList);

        updateBatch(msnList, "qty,dtlSeq,eventCode,eventValue,mo");

        SmatInsertMaterialSnHistoryIn msnHisIn = new SmatInsertMaterialSnHistoryIn();
        msnHisIn.setMsnStsList(msnList);
        ServiceBeanUtil.getBean(SmatInsertMaterialSnHistoryService.class).insertMaterialSnHistory(msnHisIn);

        insertBatch(psnList);

        SmfrInsertProductSerialHistoryIn psnHisIn = new SmfrInsertProductSerialHistoryIn();
        psnHisIn.setPsnStsList(psnList);
        ServiceBeanUtil.getBean(SmfrInsertProductSerialHistoryService.class).insertProductSerialHistory(psnHisIn);

        SmfrSaveScanMaterialToPsnAndPrintOut out = new SmfrSaveScanMaterialToPsnAndPrintOut();
    }
}